package cn.heycm.cachedrequest.util;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.text.SimpleDateFormat;

@Slf4j
public class Jackson {

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    static {
        OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        OBJECT_MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        OBJECT_MAPPER.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    private Jackson() {
    }

    public static <T> String toJson(T obj) {
        if (obj == null) {
            return null;
        }
        if (obj instanceof String) {
            return obj.toString();
        }
        try {
            return OBJECT_MAPPER.writeValueAsString(obj);
        } catch (Exception e) {
            log.error("Parse Object to String error : {}", e.getMessage(), e);
        }
        return null;
    }

    public static String toJson(byte[] bytes) {
        if (bytes == null || bytes.length == 0) {
            return null;
        }
        try {
            return OBJECT_MAPPER.readTree(bytes).toString();
        } catch (IOException e) {
            log.error("Parse Bytes to Json error : {}", e.getMessage(), e);
        }
        return null;
    }

    public static <T> byte[] toJsonBytes(T obj) {
        if (obj == null) {
            return null;
        }
        try {
            return OBJECT_MAPPER.writeValueAsBytes(obj);
        } catch (JsonProcessingException e) {
            log.error("Parse Object to byte[] error : {}", e.getMessage(), e);
        }
        return null;
    }

    public static <T> T toObject(String json, Class<T> clazz) {
        if (json != null && clazz != null) {
            try {
                return clazz.equals(String.class) ? (T) json : OBJECT_MAPPER.readValue(json, clazz);
            } catch (Exception e) {
                log.error("Parse String to Object error : {}", e.getMessage(), e);
            }
        }
        return null;
    }

    public static <T> T toObject(byte[] bytes, Class<T> clazz) {
        if (bytes != null && bytes.length > 0 && clazz != null) {
            try {
                return OBJECT_MAPPER.readValue(bytes, clazz);
            } catch (Exception e) {
                log.error("Parse byte[] to Object error : {}", e.getMessage(), e);
            }
        }
        return null;
    }
}
